#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/ether.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <net/if.h> // struct ifconf
#include "get_interface.h"
#include "tools.h"
int interface_num = 0;                  // 接口数量
INTERFACE net_interface[MAXINTERFACES]; // 接口数据

/**********************************************
函数: int get_interface_num()
功能: 获取到的本地网卡总数
参数: 无
返回值: 失败返回0
***********************************************/
int get_interface_num()
{
    return interface_num;
}

/**********************************************
函数: int getinterface(int sockfd)
功能: 获取网卡信息
参数: socket文件描述符
返回值: 失败返回-1
***********************************************/
int getinterface(int sockfd)
{
    struct ifreq buf[MAXINTERFACES]; // ifreq结构数组  临时存放接口数据
    memset(buf, 0, sizeof(buf));
    struct ifconf ifc; // ifconf结构体
    // 初始化
    ifc.ifc_len = sizeof(buf);
    ifc.ifc_buf = (caddr_t)buf;
    // 获得接口列表
    if (-1 == ioctl(sockfd, SIOCGIFCONF, (char *)&ifc))
    {
        perror("SIOCGIFCONF ioctl");
        return -1;
    }
    // 接口数量
    interface_num = ifc.ifc_len / sizeof(struct ifreq);

    // 遍历每个接口
    int if_len = interface_num;
    while (if_len-- > 0) // 每次递减
    {
        // 接口名称
        sprintf(net_interface[if_len].name, "%s", buf[if_len].ifr_name); // 保存接口名
        /* 获得接口标志 */
        if (!(ioctl(sockfd, SIOCGIFFLAGS, (unsigned char *)&buf[if_len])))
        {
            // 接口状态
            if (buf[if_len].ifr_flags & IFF_UP) // 判断是否启用状态
            {
                net_interface[if_len].flag = 1; // 启用
            }
            else
            {
                net_interface[if_len].flag = 0; // 停用
            }
        }
        else // 获取网卡启用状态失败
        {
            char str[256];
            sprintf(str, "SIOCGIFFLAGS ioctl %s", buf[if_len].ifr_name);
            perror(str);
        }
        /* IP地址 */
        if (!ioctl(sockfd, SIOCGIFADDR, (unsigned char *)&buf[if_len]))
        {
            memcpy(net_interface[if_len].ip, &((struct sockaddr_in *)(&buf[if_len].ifr_addr))->sin_addr, 4); // 保存ip
        }
        else
        {
            char str[256];
            sprintf(str, "SIOCGIFADDR ioctl %s", buf[if_len].ifr_name);
            perror(str);
        }
        /* 子网掩码 */
        if (!ioctl(sockfd, SIOCGIFNETMASK, (unsigned char *)&buf[if_len]))
        {
            memcpy(net_interface[if_len].netmask, &((struct sockaddr_in *)(&buf[if_len].ifr_addr))->sin_addr, 4); // 保存子网掩码
        }
        else
        {
            char str[256];
            sprintf(str, "SIOCGIFNETMASK ioctl %s", buf[if_len].ifr_name);
            perror(str);
        }
        /* 广播地址 */
        if (!ioctl(sockfd, SIOCGIFBRDADDR, (unsigned char *)&buf[if_len]))
        {
            memcpy(net_interface[if_len].br_ip, &((struct sockaddr_in *)(&buf[if_len].ifr_addr))->sin_addr, 4);
        }
        else
        {
            char str[256];
            sprintf(str, "SIOCGIFBRDADDR ioctl %s", buf[if_len].ifr_name);
            perror(str);
        }
        /* MAC地址 */
        if (!ioctl(sockfd, SIOCGIFHWADDR, (unsigned char *)&buf[if_len]))
        {
            memcpy(net_interface[if_len].mac, (unsigned char *)(buf[if_len].ifr_hwaddr.sa_data), 6);
        }
        else
        {
            char str[256];
            sprintf(str, "SIOCGIFBRDADDR ioctl %s", buf[if_len].ifr_name);
            perror(str);
        }
    }
    return interface_num;
}
/**********************************************
函数: INTERFACE* find_ether(unsigned char ip[4])
功能: 查找网卡信息
参数: 需要查询的ip
返回值: 失败返回NULL
***********************************************/
INTERFACE *find_ether(unsigned char ip[4])
{
    union IP tmp_ip;
    tmp_ip.ip_in = *(unsigned int *)ip;
    union IP eth_ip;   // 网卡ip
    union IP eth_mask; // 网卡掩码
    for (int i = 0; i < interface_num; i++)
    {
        eth_ip.ip_in = *(unsigned int *)(net_interface[i].ip);        // 临时拷贝ip
        eth_mask.ip_in = *(unsigned int *)(net_interface[i].netmask); // 取出本机网卡的子网掩码
        // ip地址 & 掩码 如果相等则是同一网段
        if ((eth_ip.ip_in & eth_mask.ip_in) == (tmp_ip.ip_in & eth_mask.ip_in))
        {
            return &net_interface[i];
        }
    }
    return NULL;
}
/**********************************************
函数: int is_local(unsigned char ip[4])
功能: 判断ip是否是本机的
参数: 需要查询的ip
返回值: 不是本机返回-1 本机返回0
***********************************************/
int is_local(unsigned char ip[4])
{
    union IP tmp_ip;
    tmp_ip.ip_in = *(unsigned int *)ip;
    union IP eth_ip; // 网卡ip
    for (int i = 0; i < interface_num; i++)
    {
        eth_ip.ip_in = *(unsigned int *)(net_interface[i].ip); // 临时拷贝ip
        // ip地址 相等
        if (eth_ip.ip_in == tmp_ip.ip_in)
        {
            return 0;
        }
    }
    return -1;
}